package com.yeskery.nut.web.demo.biz;

import com.yeskery.nut.annotation.bean.Autowired;
import com.yeskery.nut.annotation.bean.Component;
import com.yeskery.nut.annotation.transaction.Transactional;
import com.yeskery.nut.event.ApplicationEventPublisher;
import com.yeskery.nut.extend.i18n.MessageService;
import com.yeskery.nut.web.demo.common.Log;
import com.yeskery.nut.web.demo.common.R;
import com.yeskery.nut.web.demo.common.UserContext;
import com.yeskery.nut.web.demo.domain.Order;
import com.yeskery.nut.web.demo.domain.Product;
import com.yeskery.nut.web.demo.domain.User;
import com.yeskery.nut.web.demo.dto.OrderDto;
import com.yeskery.nut.web.demo.dto.TakeOrderDto;
import com.yeskery.nut.web.demo.dto.UserDto;
import com.yeskery.nut.web.demo.event.TakeOrderTransactionalEvent;
import com.yeskery.nut.web.demo.exception.BusinessException;
import com.yeskery.nut.web.demo.service.OrderService;
import com.yeskery.nut.web.demo.service.ProductService;
import com.yeskery.nut.web.demo.service.UserService;
import com.yeskery.nut.web.demo.service.WalletService;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单biz
 * @author Yeskery
 * 2023/7/28
 */
@Component
public class OrderBiz {

    @Autowired
    private OrderService orderService;

    @Autowired
    private UserService userService;

    @Autowired
    private WalletService walletService;

    @Autowired
    private ProductService productService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private ApplicationEventPublisher eventPublisher;

    /**
     * 获取用户订单列表
     * @return
     */
    @Log("获取用户订单列表")
    public List<OrderDto> getUserOrderList() {
        UserDto user = UserContext.getUser();
        List<Order> orderList = orderService.lambdaQuery().eq(Order::getUserId, user.getId()).list();
        if (CollectionUtils.isEmpty(orderList)) {
            return Collections.emptyList();
        }
        List<Integer> userIdList = orderList.stream().map(Order::getUserId).collect(Collectors.toList());
        List<User> userList = new ArrayList<>(userIdList.size());
        if (!CollectionUtils.isEmpty(userIdList)) {
            userList.addAll(userService.lambdaQuery()
                    .select(User::getId, User::getNickname)
                    .in(User::getId, userIdList)
                    .list());
        }
        List<Integer> productIdList = orderList.stream().map(Order::getProductId).collect(Collectors.toList());
        List<Product> productList = new ArrayList<>(productIdList.size());
        if (!CollectionUtils.isEmpty(productIdList)) {
            productList.addAll(productService.lambdaQuery()
                    .select(Product::getId, Product::getName)
                    .in(Product::getId, productIdList)
                    .list());
        }
        return orderList.stream()
                .map(r -> {
                    OrderDto orderDto = new OrderDto();
                    BeanUtils.copyProperties(r, orderDto);
                    return orderDto;
                })
                .peek(r -> userList.stream().filter(u -> u.getId().equals(r.getUserId())).findFirst().ifPresent(u -> r.setNickname(u.getNickname())))
                .peek(r -> productList.stream().filter(p -> p.getId().equals(r.getProductId())).findFirst().ifPresent(p -> r.setProductName(p.getName())))
                .collect(Collectors.toList());
    }

    /**
     * 下单
     * @param dto
     * @return
     */
    @Log("用户下单")
    @Transactional(rollbackFor = Exception.class)
    public R<?> takeOrder(TakeOrderDto dto) {
        UserDto user = UserContext.getUser();
        Product product = productService.getById(dto.getProductId());
        if (product == null) {
            return R.fail(messageService.getMessage("order.product.notfound"));
        } else if (product.getStock() <= 0) {
            return R.fail(messageService.getMessage("order.product.stock.empty"));
        } else if (product.getStock() < dto.getNum()) {
            return R.fail(messageService.getMessage("order.product.stock.insufficient"));
        }
        // 扣除商品库存
        boolean result = productService.deductStock(product.getId(), dto.getNum());
        if (!result) {
            return R.fail(messageService.getMessage("order.product.stock.insufficient"));
        }
        // 保存订单记录
        Order order = new Order();
        order.setUserId(user.getId());
        order.setProductId(product.getId());
        order.setNum(dto.getNum());
        if (!orderService.save(order)) {
            throw new BusinessException(messageService.getMessage("order.product.stock.fail"));
        }

        // 测试事务事件，提前发送事务消息
        eventPublisher.publishEvent(new TakeOrderTransactionalEvent(order));

        // 扣除用户积分
        result = walletService.deductPoint(user.getId(), product.getPrice() * dto.getNum());
        if (!result) {
            throw new BusinessException(messageService.getMessage("order.point.insufficient"));
        }
        return R.ok(order.getId(), messageService.getMessage("order.ok"));
    }
}
